package cn.gok.oa.attendance.controller;


import cn.gok.oa.attendance.dto.AttendanceDto;
import cn.gok.oa.attendance.dto.ClockInDto;
import cn.gok.oa.attendance.entity.TbAttendance;
import cn.gok.oa.attendance.entity.ExcelData;
import cn.gok.oa.attendance.service.ITbAttendanceService;
import cn.gok.oa.attendance.vo.AttendanceVo;
import cn.gok.oa.configuration.entity.TbConfiguration;
import cn.gok.oa.configuration.service.ITbConfigurationService;
import cn.gok.oa.log.LogAnnotation;
import cn.gok.oa.system.service.ITbUserDetailService;
import cn.gok.oa.util.DistanceUtil;
import cn.gok.oa.util.ResultData;
import com.alibaba.excel.EasyExcel;
import com.auth0.jwt.JWT;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.text.ParseException;
import java.util.*;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author gok
 * @since 2022-08-04
 */
@RestController
@RequestMapping("/attendanceMgt")
public class TbAttendanceController {
    @Autowired
    ITbAttendanceService attendanceService;

    @Autowired
    ITbUserDetailService userDetailService;

    @Autowired
    ITbConfigurationService configurationService;

    @RequestMapping(value = "/record",method = RequestMethod.GET)
    @LogAnnotation("月份获取考勤表")
    public ResultData queryByMonth(int month,HttpServletRequest httpServletRequest){
        String token = httpServletRequest.getHeader("token");
        int userId = (Integer.parseInt(JWT.decode(token).getAudience().get(0)));
        List<TbAttendance> list = attendanceService.queryByMonth(userId,month);
        ResultData result = ResultData.success();
        result.setData(list);
        System.out.println(list);
        return result;
    }


    @RequestMapping(value = "/clockIn",method = RequestMethod.POST)
    @ResponseBody
    @LogAnnotation("签到")
    public ResultData clockIn(@RequestBody ClockInDto clockInDto, HttpServletRequest httpServletRequest) throws ParseException {
        String token = httpServletRequest.getHeader("token");
        //先判断数据库中有没有当天打卡记录，有则返回已打卡信息
        QueryWrapper<TbAttendance> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().eq(TbAttendance::getUserId,Integer.parseInt(JWT.decode(token).getAudience().get(0)));
        queryWrapper.between("time",clockInDto.getTime().split(" ")[0]+" 00:00:00",clockInDto.getTime().split(" ")[0]+" 12:00:00");
        queryWrapper.lambda().eq(TbAttendance::getType,0);
        if (attendanceService.getOne(queryWrapper) != null){
            ResultData result = ResultData.fail();
            result.setMsg("该用户当天已经打卡！");
            return result;
        }
        //读取配置表信息，判断用户是否在规定打卡范围内打卡
        TbConfiguration configuration= configurationService.getById(1);
        String[] split = configuration.getLngLat().split("#");
        if (Double.parseDouble(DistanceUtil.getDistance(clockInDto.getLongitude()+"",clockInDto.getLatitude()+"",split[0],split[1])) > Integer.parseInt(split[2])) {
            return new ResultData("1","不在打卡范围内！",null);
        }
        TbAttendance attendance = new TbAttendance();
        attendance.setTime(clockInDto.getTime());
        attendance.setUserId(Integer.parseInt(JWT.decode(token).getAudience().get(0)));
        attendance.setLocation(clockInDto.getLongitude()+"#"+clockInDto.getLatitude());
        attendance.setType(0);
        int temp = 0;
        try {
            temp = attendanceService.clockIn(attendance);
        }catch (RuntimeException e){
            ResultData result = ResultData.fail();
            result.setMsg("不在打卡时间！");
            return result;
        }
        if (temp > 0){
//            插入成功后将状态由数字转为文字，交给前端渲染
            String status = null;
            if(attendance.getAttendanceStatus()==0){
                status = "正常";
            } else if (attendance.getAttendanceStatus()==1) {
                status = "迟到";
            }
            //创建map添加数据
            Map<String, Object> attendance_status = new HashMap<>();
            attendance_status.put("打卡状态",status);
            ResultData result = ResultData.success();
            result.setData(attendance_status);
            return result;
        }else {
            return ResultData.fail();
        }
    }

    @RequestMapping(value = "/signOut",method = RequestMethod.POST)
    @ResponseBody
    @LogAnnotation("签退")
    public ResultData signOut(@RequestBody ClockInDto clockInDto, HttpServletRequest httpServletRequest) throws ParseException {
        String token = httpServletRequest.getHeader("token");
        //判断用户当天是否有签到，签到记录为缺勤则为未签到状态
        QueryWrapper<TbAttendance> queryWrapperClickIn = new QueryWrapper();
        queryWrapperClickIn.lambda().eq(TbAttendance::getType,0);
        queryWrapperClickIn.between("time",clockInDto.getTime().split(" ")[0]+" 00:00:00",clockInDto.getTime().split(" ")[0]+" 12:00:00");
        queryWrapperClickIn.lambda().eq(TbAttendance::getUserId,Integer.parseInt(JWT.decode(token).getAudience().get(0)));
        queryWrapperClickIn.lambda().eq(TbAttendance::getAttendanceStatus,2);
        if (attendanceService.getOne(queryWrapperClickIn) != null){
            ResultData result = ResultData.fail();
            result.setMsg("该用户当天未签到，无法签退！");
            return result;
        }
        //先判断数据库中有没有当天打卡记录，有则返回已打卡信息
        QueryWrapper<TbAttendance> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().eq(TbAttendance::getUserId,Integer.parseInt(JWT.decode(token).getAudience().get(0)));
        queryWrapper.between("time",clockInDto.getTime().split(" ")[0]+" 12:00:00",clockInDto.getTime().split(" ")[0]+" 23:59:59");
        queryWrapper.lambda().eq(TbAttendance::getType,1);
        queryWrapper.lambda().eq(TbAttendance::getAttendanceStatus,4);
        if (attendanceService.getOne(queryWrapper) != null){
            ResultData result = ResultData.fail();
            result.setMsg("该用户当天已经签退！");
            return result;
        }
        //读取配置表信息，判断用户是否在规定打卡范围内打卡
        TbConfiguration configuration= configurationService.getById(1);
        String[] split = configuration.getLngLat().split("#");
        if (Double.parseDouble(DistanceUtil.getDistance(clockInDto.getLongitude()+"",clockInDto.getLatitude()+"",split[0],split[1])) > Integer.parseInt(split[2])) {
            return new ResultData("1","不在打卡范围内！",null);
        }
        //将对象的基本信息赋值
        TbAttendance attendance = new TbAttendance();
        attendance.setTime(clockInDto.getTime());
        attendance.setUserId(Integer.parseInt(JWT.decode(token).getAudience().get(0)));
        attendance.setLocation(clockInDto.getLongitude()+"#"+clockInDto.getLatitude());
        attendance.setType(1);
        int temp = 0;
        try {
            temp = attendanceService.signOut(attendance);
        }catch (RuntimeException e){
            ResultData result = ResultData.fail();
            result.setMsg("不在打卡时间！");
            return result;
        }
        if (temp > 0){
//            插入成功后将状态由数字转为文字，交给前端渲染
            String status = null;
            if(attendance.getAttendanceStatus()==4){
                status = "正常";
            } else if (attendance.getAttendanceStatus()==3) {
                status = "早退";
            }
            //创建map添加数据
            Map<String, Object> attendance_status = new HashMap<>();
            attendance_status.put("打卡状态",status);
            ResultData result = ResultData.success();
            result.setData(attendance_status);
            return result;
        }else {
            return ResultData.fail();
        }
    }
    //申请补打卡审批通过后调用修改考勤状态

    @RequestMapping(value = "/update",method = RequestMethod.PUT)
    @LogAnnotation("补打卡")
    public ResultData updateStatus(int attendanceId){
        TbAttendance attendance = attendanceService.getById(attendanceId);
        //如果需要更改的为早退类型，则需要把早退记录删除
        QueryWrapper<TbAttendance> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().eq(TbAttendance::getType,1);
        queryWrapper.between("time",attendance.getTime().split(" ")[0]+" 12:00:00",attendance.getTime().split(" ")[0]+" 23:59:59");
        queryWrapper.lambda().eq(TbAttendance::getUserId,attendance.getUserId());
        queryWrapper.lambda().eq(TbAttendance::getAttendanceStatus,3);
        if(attendanceService.getOne(queryWrapper) != null){
            attendanceService.remove(queryWrapper);
        }
        attendance.setAttendanceStatus(0);
        if (attendanceService.updateById(attendance)){
            return ResultData.success();
        }else {
            return ResultData.fail();
        }
    }

    @RequestMapping(value = "/statistics",method = RequestMethod.GET)
    @LogAnnotation("考勤统计")
    public ResultData statistics(AttendanceDto dto) throws ParseException {
        List<AttendanceVo> attendances = attendanceService.getList(dto);
        if (attendances == null){
            return ResultData.fail();
        }
        ResultData resultData = ResultData.success();
        resultData.setData(attendances);
        return resultData;

    }
    /**
     * 文件下载（失败了会返回一个有部分数据的Excel）
     * <p>1. 创建excel对应的实体对象 参照{@link }
     * <p>2. 设置返回的 参数
     * <p>3. 直接写，这里注意，finish的时候会自动关闭OutputStream,当然你外面再关闭流问题不大
     */

    @RequestMapping(value = "/download",method = RequestMethod.GET)
    @LogAnnotation("导出excel")
    public void download(HttpServletResponse response) throws IOException, ParseException {
        // 这里注意 有同学反应使用swagger 会导致各种问题，请直接用浏览器或者用postman
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("测试", "UTF-8");
        List<AttendanceVo> attendanceVos = attendanceService.Excel();
        List<ExcelData> excelData = new ArrayList<>();
        for (int i = 0; i < attendanceVos.size(); i++) {
            ExcelData data = new ExcelData();
            BeanUtils.copyProperties(attendanceVos.get(i),data);
            if (attendanceVos.get(i).getAttendanceStatus() == 0){
                data.setAttendanceStatus("正常");
            }else if (attendanceVos.get(i).getAttendanceStatus() == 1){
                data.setAttendanceStatus("迟到");
            } else if (attendanceVos.get(i).getAttendanceStatus() == 3) {
                data.setAttendanceStatus("早退");
            } else if (attendanceVos.get(i).getAttendanceStatus() == 2) {
                data.setAttendanceStatus("缺勤");
            }
            excelData.add(data);
        }
        EasyExcel.write(response.getOutputStream(), ExcelData.class).sheet("模板").doWrite(excelData);
    }
}
